/*
 *  HTTPRequestHelper.cpp
 *  AMPlugin
 *
 *  Created by Tiet Anh Vu on 5/24/12.
 *  Copyright 2012 __MyCompanyName__. All rights reserved.
 *
 */

#include "HTTPRequestHelper.h"
#include "AMPID.h"
#include "AMGlobal.h"
#include "AMPLogDataRecord.h"
#include "AMPLogCenter.h"

//extern vector<pt_assignStr> g_assignmentPtr;
#define NUMT 4

/********************************************************************************************************************
 *****Function: getDataFromURL
 *****Creator:  Toan Nguyen
 *****IN: const string &url
 *****out: 
 *****Objective: get data request from url
 ********************************************************************************************************************/
string HTTPRequestHelper::getDataFromURL(const string &url) {
	//progressBar = RangeProgressBar("Please wait...", 0, 100, kTrue, kFalse, nil, kFalse);
	string buffer;
	CURL *curl;
	CURLcode result;
	cout << "url:" << url << endl;
	SaveLogCenterData(url);
	curl = curl_easy_init();
	
	if (curl)
	{
		HTTPRequestHelper::setProxyServer(curl);
		curl_easy_setopt(curl, CURLOPT_URL, url.c_str()  );
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);
		// Internal CURL progressmeter must be disabled if we provide our own callback
		//curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
		// Install the callback function
		//curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_func);
		
		result = curl_easy_perform(curl);//http get performed
		 
		curl_easy_cleanup(curl);//must cleanup
		//cout << "content:" << buffer << endl;
		//error codes: http://curl.haxx.se/libcurl/c/libcurl-errors.html
		if (result == CURLE_OK && (buffer != ""))
			return buffer;	
		//curl_easy_strerror was added in libcurl 7.12.0
		cerr << "error: " << result << " " << curl_easy_strerror(result) <<endl;
		return "Error Code";
	}
	return "";
}

/********************************************************************************************************************
 *****Function: writer
 *****Creator:  Toan Nguyen
 *****IN: char *data, size_t size, size_t nmemb, string *buffer
 *****out: 
 *****Objective: write data to local file
 ********************************************************************************************************************/
int HTTPRequestHelper::writer(char *data, size_t size, size_t nmemb, string *buffer)
{
	//cout << "writer is running" << endl;
	int result = 0;
	if (buffer != NULL)
	{
		buffer->append(data, size * nmemb);
		result = size * nmemb;
	}
	return result;
}

/********************************************************************************************************************
 *****Function: setProxyServer
 *****Creator:  Toan Nguyen
 *****IN: CURL *Handlecurl
 *****out: 
 *****Objective: set proxy server
 ********************************************************************************************************************/
bool HTTPRequestHelper::setProxyServer(CURL *Handlecurl) {

	if(g_ProxyEnable == FALSE)	//auto mode
		return TRUE;

	// setting proxy for manual mode
	string proxydomain = g_ProxyServer + ":" + g_ProxyPort;
	//string proxydomain = "192.168.2.242:8888";
	//cout << "proxydomain:" << proxydomain << endl;
	curl_easy_setopt(Handlecurl, CURLOPT_PROXY, proxydomain.c_str());
	
	if(g_ProxyAuthEnable == TRUE)
	{
		curl_easy_setopt(Handlecurl, CURLOPT_PROXYUSERPWD, g_ProxyAuthen.c_str());
	}
	return TRUE;
}

/********************************************************************************************************************
 *****Function: loginToCMSServer
 *****Creator:  Toan Nguyen
 *****IN: RangeProgressBar * DlgProg, int min, int max
 *****out: 
 *****Objective: login to Audience Media CMS
 ********************************************************************************************************************/
int HTTPRequestHelper::loginToCMSServer(RangeProgressBar * DlgProg, int min, int max) {
	string buffer;
	string _error_info;
	long respcode = 305;
	//std::string authentication = UsernameLogin + ":" + PasswordLogin;
	//std::string Domain = DomainLogin + "/api/amp/v1/indesign/login";
	string apiPrefix = API_PREFIX;
	std::string authentication = g_Username + ":" + g_Password;
	std::string Domain = g_Domain + "/" + apiPrefix + "/login";
	CURL *curl;
	CURLcode _result;
	g_Authentication = authentication;
	//cout << "Domain: " << Domain << endl;
	//cout << "name: " << g_Username << " Pass:" << g_Password << endl; 
	//cout << "Auth: " << authentication.c_str() << endl;
	curl = curl_easy_init();
	
	if (curl)
	{
		HTTPRequestHelper::setProxyServer(curl);
		//curl_easy_setopt(curl, CURLOPT_URL, url.c_str()  );
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str()  );
		//_______________________________________________________
		// progress function 
		struct myprogress AMPDlgProg;
		AMPDlgProg.lastruntime = 0;
		AMPDlgProg.curl = curl;
		AMPDlgProg.MinPos = min;
		AMPDlgProg.MaxPos = max/3;
		AMPDlgProg.DownUp = UPLOADCOMMAND;
		AMPDlgProg.Progress = DlgProg;
		//struct AMPProgressDlgInfo AMPDlgProg;
		//AMPDlgProg.g_dialog = iDlgProg;
		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress);
		curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &AMPDlgProg);
		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
		//_______________________________________________________
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());

		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
		
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 25);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 25);
		
		_result = curl_easy_perform(curl);//http get performed
		curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &respcode);
		
		curl_easy_cleanup(curl);//must cleanup
		cout << "Return code :" << respcode << " - " << _result << endl;
		cout << "======= Login buffer: " << buffer << endl;
		if (_result != CURLE_OK) {
			cout << "error log in to server" << _result << endl;
			_error_info = "log in to server error";
			SaveLogCenterData(_error_info);
			//AMPLogCenter::DataLogCenter(AMPPLUGIN_COULDNT_CONNECT);
			DlgProg->SetPosition(max);
			return 0;
		}else if (respcode == 407)
		{
			cout << "Proxy Authentication Required" << endl;
			_error_info = "Proxy Authentication Required";
			SaveLogCenterData(_error_info);
			//AMPLogCenter::DataLogCenter(AMPPLUGIN_COULDNT_RESOLVE_PROXY);
			DlgProg->SetPosition(max);
			return 407;
		}
		// Analysic json link
		Json::Value root;   // will contains the root value after parsing.
		Json::Reader reader;
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			cout << "Cannot parse JSON" << endl;
			_error_info = "Wrong usename and password, cannot parsing JSON";
			SaveLogCenterData(_error_info);
			//AMPLogCenter::DataLogCenter(AMPPLUGIN_COULDNT_PARSE_JSON);
			DlgProg->SetPosition(max);
			return 401;
		}

		//{"user":{"id":"14","login":"admin","name":"Administrator User","email":"thu.pham@audiencemedia.com"}}
		
		const Json::Value userid = root["user"]["id"];
		//cout << "userid: " << userid << endl;
		if (atoi(userid.asString().c_str()) <= 0) {
			cout << "Wrong usename and password" << endl;
			_error_info = "Wrong usename and password, user_id:" + userid.asString();
			SaveLogCenterData(_error_info);
			//AMPLogCenter::DataLogCenter(AMPPLUGIN_LOGIN_DENIED);
			DlgProg->SetPosition(max);
			return 401;
		}
		const Json::Value urlPreImg = root["user"]["default_preview_image"];
		string __url = urlPreImg.asString().c_str();
		AMPDlgProg.lastruntime = 0;
		AMPDlgProg.curl = curl;
		AMPDlgProg.MinPos = max/3;
		AMPDlgProg.MaxPos = max;
		AMPDlgProg.DownUp = UPLOADCOMMAND;
		AMPDlgProg.Progress = DlgProg;
		g_ImagePreview = HTTPRequestHelper::getImagePreview(__url, AMPDlgProg);
	}
	
	//return FALSE;
	//cout << "Response Code login:" << respcode << endl;
	_error_info = "Log in to server successful";
	SaveLogCenterData(_error_info);
	DlgProg->SetPosition(max);
	return respcode;
}


string HTTPRequestHelper::getImage(const string& url, myprogress image_progressbar)
{
	
	CURL *curl;
	CURLcode res;
	FILE *ftpfile;
	FILE *respfile;
	
	string __url[2];
	int xx, ImageSize = 1;
	if(url.find("[[]]") != string::npos)
	{
		__url[0] = url.substr(0, url.find("[[]]"));
		__url[1] = url.substr(url.find("[[]]")+4, url.length());
		ImageSize = 2;
	}else
	{
		__url[0] = url;
	}

	//cout << "URL1: " << __url[0] << endl;
	//cout << "URL2: " << __url[1] << endl;
	// generate filename from url
	string filename;
	string ftpFilePath;
	string sdkfilename;
	string return_SDKFileName = "";
	for(xx=0; xx < ImageSize; xx++)
	{
		//url = __url[xx].substr(0, __url[xx].length());
		
		//filename = url.substr(url.find_last_of("/")+1);
		filename = __url[xx].substr(__url[xx].find_last_of("/")+1);
		ftpFilePath = g_System_WorkspaceDir + "/" + filename; 
		sdkfilename = g_SDK_WorkspaceDir + ":" + filename;
		string respfilePath = g_System_WorkspaceDir + "/resp" + filename;
		const char *filePath = ftpFilePath.c_str();
		const char *respFilePath = respfilePath.c_str();
		

		//cout << "ftpFilepath: " << ftpFilePath << endl;
		
		/* local file name to store the file as */ 
		//ftpfile = fopen("Macintosh HD:Projects:InDesign-Plugin:bbcgoodefood:1:11:aaa.jpg", "wb"); /* b is binary, needed on win32 */ 
		ftpfile = fopen(filePath, "wb"); /* b is binary, needed on win32 */ 
		
		/* local file name to store the FTP server's response lines in */ 
		respfile = fopen(respFilePath, "wb"); /* b is binary, needed on win32 */ 
		//respfile = fopen("Macintosh HD:Projects:InDesign-Plugin:bbcgoodefood:1:11:bbb.jpg", "wb"); /* b is binary, needed on win32 */ 
		
		curl = curl_easy_init();
		if(curl) {
			HTTPRequestHelper::setProxyServer(curl);
			/* Get a file listing from sunet */ 
			curl_easy_setopt(curl, CURLOPT_URL, __url[xx].c_str());
			curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
			//curl_easy_setopt(curl, CURLOPT_URL, "http://grazia.api.test.audiencemedia.com/var/grazia/storage/application/MensShirts.zip");
			//curl_easy_setopt(curl, CURLOPT_USERPWD, authentication);
			curl_easy_setopt(curl, CURLOPT_WRITEDATA, ftpfile);
			
			curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress);	//add progress download
			// pass the struct pointer into the progress function 
			curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &image_progressbar);
			curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
			
			/* If you intend to use this on windows with a libcurl DLL, you must use
			 CURLOPT_WRITEFUNCTION as well */ 
			curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HTTPRequestHelper::file_write_response);
			curl_easy_setopt(curl, CURLOPT_WRITEHEADER, respfile);
			curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 60);
			curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60);
			res = curl_easy_perform(curl);
			
			/* always cleanup */ 
			curl_easy_cleanup(curl);
		}
		
		fclose(ftpfile); /* close the local file */ 
		fclose(respfile); /* close the response file */ 
		//string deleteLink = "rm -rf " + respfilePath;
		//system(deleteLink.c_str());
		
		if(xx == 0)
		{
			return_SDKFileName = sdkfilename;
		}else
		{
			return_SDKFileName = return_SDKFileName + "||||" + sdkfilename;
		}
	}
	//cout << "return_SDKFileName:" << return_SDKFileName << endl;
	return return_SDKFileName;
	
	
}

/********************************************************************************************************************
 *****Function: file_write_response
 *****Creator:  Toan Nguyen
 *****IN: void *ptr, size_t size, size_t nmemb, void *data
 *****out: 
 *****Objective: write file to local machine
 ********************************************************************************************************************/
int HTTPRequestHelper::file_write_response(void *ptr, size_t size, size_t nmemb, void *data)
{
	FILE *writehere = (FILE *)data;
	return fwrite(ptr, size, nmemb, writehere);
}


int HTTPRequestHelper::header_response(void *ptr, size_t size, size_t nmemb, void *data)
{
	FILE *writehere = (FILE *)data;
	return fwrite(ptr, size, nmemb, writehere);
}

/********************************************************************************************************************
 *****Function: getStoryURL
 *****Creator:  Toan Nguyen
 *****IN: const string &url, string &error
 *****out: 
 *****Objective: get story/content/icml request from cms
 ********************************************************************************************************************/
string HTTPRequestHelper::getStoryURL(const string &url, string &error) {
	
	//progressBar = RangeProgressBar("Please wait...", 0, 100, kTrue, kFalse, nil, kFalse);
	string buffer;
	string _error_info;
	string urlRequest;
	CURL *curl;
	CURLcode result;
	//cout << url << endl;
	curl = curl_easy_init();
	
	if (curl)
	{
		HTTPRequestHelper::setProxyServer(curl);
		curl_easy_setopt(curl, CURLOPT_URL, url.c_str()  );
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 100);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 100);
		
		// Internal CURL progressmeter must be disabled if we provide our own callback
		//curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
		// Install the callback function
		//curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_func);		
		
		result = curl_easy_perform(curl);//http get performed
		
		curl_easy_cleanup(curl);//must cleanup
		cout << buffer << endl;
		// Analysic json link
		Json::Value root;   // will contains the root value after parsing.
		Json::Reader reader;
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			//cout << "cannot parse JSON HTTPRequestHelper::getStoryURL" << endl;
			error = "Failed to get page from server\n\nPlease try again";
			_error_info = "Failed to get page from server, couldn't parsing json, buffer:" + buffer;
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_COULDNT_PARSE_JSON);
			return "";
		}
		
		const Json::Value success = root["success"];
		if (success.asBool() == FALSE) {
			Json::Value errorText = root["text"];
			error = errorText.asString();
			_error_info = "Failed to get page from server, return text:" + errorText.asString();
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_COULDNT_CONNECTION_ERROR);
			return "";
		}
		
		const Json::Value page_name = root["package_id"];
		//g_IDMLOpen = page_name.asString();
		g_Package_id = page_name.asString(); 
		const Json::Value pages_package = root["pages_package"];
		urlRequest = pages_package.asString();
		const Json::Value session_id = root["session"]["session_id"];
		n_mSessionID = session_id.asString();
		const Json::Value user_id = root["session"]["user_id"];
		n_mSessionUserID = user_id.asString();
		const Json::Value session_timeout = root["session"]["session_expire_timeout"];
		n_mSessionTimeOut = session_timeout.asInt();
		n_mSessionCounterReset = 0;
		//n_mSessionTotalCounterReset = (n_mSessionTimeOut - 300)/10;
		n_mSessionTotalCounterReset = (n_mSessionTimeOut - 300)/180;
		if (result == CURLE_OK)
			return urlRequest;
		//curl_easy_strerror was added in libcurl 7.12.0
		cerr << "error: " << result << " " << curl_easy_strerror(result) <<endl;
		error = "Failed to connect to server\n\nPlease try again";
		_error_info = "Failed to connect to server";
		SaveLogCenterData(_error_info);
		AMPLogCenter::DataLogCenter(AMPPLUGIN_COULDNT_CONNECT);
		return "";
	}
	return "";
}

/********************************************************************************************************************
 *****Function: dump_buffer
 *****Creator:  Toan Nguyen
 *****IN: void *buffer, int32 buffer_size
 *****out: 
 *****Objective: read data from local file
 ********************************************************************************************************************/
string HTTPRequestHelper::dump_buffer(void *buffer, int32 buffer_size){
	int32 i;
	string ch;
	for(i = 0; i < buffer_size; ++i){
		//cout << ((char *)buffer)[i] << endl;
		ch += ((char *)buffer)[i];
	}
	return ch;
}

/********************************************************************************************************************
 *****Function: readFileBytes
 *****Creator:  Toan Nguyen
 *****IN: const string &pathUpload
 *****out: 
 *****Objective: read data from local file
 ********************************************************************************************************************/
string HTTPRequestHelper::readFileBytes(const string &pathUpload){
	FILE *file;
	char *buffer;
	unsigned long fileLen;
	string retString;
	int i;
	file = fopen(pathUpload.c_str(), "rb");
	if (!file)
	{
		cout << "can't open file" << pathUpload << endl;
		return NULL;
	}
	
	fseek(file, 0, SEEK_END);
	fileLen=ftell(file);
	fseek(file, 0, SEEK_SET);
	
	buffer=(char *)malloc(sizeof(char)*(fileLen+1));
	
	if (!buffer)
	{
		fclose(file);
		cout << "can't allocate memory with size = " << fileLen << endl;
		return NULL;
	}
	
	fread(buffer, fileLen, 1, file);
	fclose(file);
	retString = dump_buffer(buffer, fileLen);;
#if _INDESIG_DEBUG
	//cout << "retString:" << retString << endl;
	//cout << "Buffer:" << buffer << endl;
	//cout << "fileLen:" << fileLen << endl;
#endif
	
	return retString;
}

/********************************************************************************************************************
 *****Function: UploadFileToCMS
 *****Creator:  Toan Nguyen
 *****IN: const string &pathFile, bool keep_session
 *****out: 
 *****Objective: check in file to Audience Media CMS
 ********************************************************************************************************************/
int HTTPRequestHelper::UploadFileToCMS(const string &pathFile, bool keep_session)
{
	string _error_info, str_keep_session = "FALSE";
	struct myprogress prog;
	//double curtime = 0;
	RangeProgressBar *progressBar;
	progressBar = new RangeProgressBar("Checking in...", 0, 200, kTrue, kFalse, nil, kFalse);
	//progressBar->SetPosition(1);
	CURL *curl;
	CURLcode res;
	string buffer;

	string Domain;
	string fileZip;
	string apiPrefix = API_PREFIX;
	Domain = g_Domain + "/" + apiPrefix + "/pages";
	//Domain = g_Domain + "/" + apiPrefix + "/fillpages";
	
	//cout << "upload zip file url: " << Domain << endl;
	if(keep_session == FALSE){
		str_keep_session = "FALSE";
	}else
	{
		str_keep_session = "TRUE";
	}
	cout << "keep session: " << str_keep_session << endl;
	//fileZip = AMPUtils::getNameFromURL(pathFile);
	
	string pageCheckout = g_pageNumberCheckOut;
	while (pageCheckout.find(" ") != string::npos) {
		pageCheckout.replace(pageCheckout.find(" "), 1, "");
	}
	pageCheckout.erase(pageCheckout.length()-1, pageCheckout.length()); // remove the last ","

	//progressbar.SetPosition(15);
	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;
	struct curl_slist *headerlist=NULL;
	static const char buf[] = "Content-Type: multipart/form-data";
	//progressBar->SetPosition(5);
	//string postdata = readFileBytes(pathFile);
	//progressbar.SetPosition(25);
	// Fill in the file upload field. This makes libcurl load data from the given file name when curl_easy_perform() is called.
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "pages_package",
				 CURLFORM_FILE, pathFile.c_str(),
				 CURLFORM_END);
	
	cout << "API:" << Domain << endl;
	cout << "path file:" << pathFile << endl;
	//cout << "UploadFileToCMS - magazine_id:" << g_Magazineid << endl;
	cout << "issue_id:" << g_Issueid << endl;
	//cout << "UploadFileToCMS - page_id:" << g_Pageid << endl;
	//cout << "UploadFileToCMS - story_id:" << g_Storyid << endl;
	//cout << "UploadFileToCMS - session_id:" << n_mSessionID << endl;
	cout << "pages: " << pageCheckout << endl;
	
	/*
	// Fill in the filename field
	//curl_formadd(&f ormpost,
	//			 &lastptr,
	//			 CURLFORM_COPYNAME, "data",
	//			 CURLFORM_COPYCONTENTS, postdata.c_str(),
	//			 CURLFORM_END);
	
	// Fill in the submit field too, even if this is rarely needed
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "magazine_id",
				 CURLFORM_COPYCONTENTS, g_Magazineid.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "issue_id",
				 CURLFORM_COPYCONTENTS, g_Issueid.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "page_id",
				 CURLFORM_COPYCONTENTS,  g_Pageid.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "story_id",
				 CURLFORM_COPYCONTENTS, g_Storyid.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "session_id",
				 CURLFORM_COPYCONTENTS, n_mSessionID.c_str(),
				 CURLFORM_END);
	*/
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "issue_id",
				 CURLFORM_COPYCONTENTS, g_Issueid.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "pages",
				 CURLFORM_COPYCONTENTS, pageCheckout.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "keep_session",
				 CURLFORM_COPYCONTENTS, str_keep_session.c_str(),
				 CURLFORM_END);
	
	curl = curl_easy_init();
	// initalize custom header list (stating that Expect: 100-continue is not wanted
	headerlist = curl_slist_append(headerlist, buf);
	//sprogressBar->SetPosition(15);
	if(curl) {
		prog.lastruntime = 0;
		prog.curl = curl;
		prog.MinPos = 0;
		prog.MaxPos = 200;
		prog.DownUp = UPLOADCOMMAND;
		prog.Progress = progressBar;
		HTTPRequestHelper::setProxyServer(curl);
		// what URL that receives this POST 
		//curl_easy_setopt(curl, CURLOPT_URL, "http://debug.dev.test.audiencemedia.com/idtest/checkin.php");
		//curl_easy_setopt(curl, CURLOPT_URL, "http://story.api.test.audiencemedia.com/api/amp/v1/indesign/story");
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		//curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime);
		curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1000);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1000);
		// progress function 
		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress);
		// pass the struct pointer into the progress function 
		curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog);
		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
		//<-- end of progress fuction
		//curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		// init post data to cms
		
		//-----Add to get key to upload cover image----
	//	curl_easy_setopt(curl, CURLOPT_HEADER, 0);
	//	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
	//	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);		
		//-------------------EOF-----------------------
		res = curl_easy_perform(curl);
	//	cout << "buffer: " << buffer << endl;
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			
			// then cleanup the formpost chain
			curl_formfree(formpost);
			// free slist
			curl_slist_free_all (headerlist);
			progressBar->SetPosition(200);
			cout << "upload curl_easy_perform: " << res << endl;
			_error_info = "Failed to checking in package to server";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UPLOAD_FAILED);
			progressBar->~RangeProgressBar();
			return FALSE;
		}
		//-----Add to get key to upload cover image----
		//Json::Value root;   // will contains the root value after parsing.
		//Json::Reader reader;
		
/*		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			cout << "cannot parse JSON HTTPRequestHelper::UploadFileToCMS" << endl;
			//progressBar->SetPosition(200);
			//progressBar->~RangeProgressBar();
			//return FALSE;
		}
*/		//const Json::Value package_id = root["package_id"];
		//g_Package_id = package_id.asString();
#if _INDESIG_DEBUG
		//cout << "package_id: " << g_Package_id << endl;
		//cout << "buffer: " << buffer << endl;
#endif
		//-------------------EOF-----------------------
		// always cleanup 
		curl_easy_cleanup(curl);
		
		// then cleanup the formpost chain
		curl_formfree(formpost);
		// free slist
		curl_slist_free_all (headerlist);
		_error_info = "Checked in package successful";
		SaveLogCenterData(_error_info);
		progressBar->SetPosition(200);
		progressBar->~RangeProgressBar();
	}
	return TRUE;
}

/********************************************************************************************************************
 *****Function: UploadCoverImageToCMS
 *****Creator:  Toan Nguyen
 *****IN: const string &pathFile, int32 OffsetImg
 *****out: 
 *****Objective: check in prevew image to Audience Media cms
 ********************************************************************************************************************/
int HTTPRequestHelper::UploadCoverImageToCMS(const string &pathFile, int32 OffsetImg)
{
	string _error_info;
	CURL *curl;
	CURLcode res;
	string Domain;
	string apiPrefix = API_PREFIX;
	//char temp[100];
	string inStr;
	stringstream outstr;
	outstr << OffsetImg;
	inStr = outstr.str();
	//sprintf( temp, "%d", OffsetImg);
	Domain = g_Domain + "/" + apiPrefix + "/pages";
	//cout << "Cover image: " << pathFile << " page_number:" << inStr << " issue_id:" << g_Issueid << endl;

	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;
	struct curl_slist *headerlist=NULL;
	static const char buf[] = "Content-Type: multipart/form-data";

	string pageCheckout = g_pageNumberCheckOut;
	while (pageCheckout.find(" ") != string::npos) {
		pageCheckout.replace(pageCheckout.find(" "), 1, "");
	}
	pageCheckout.erase(pageCheckout.length()-1, pageCheckout.length()); // remove the last ","
	cout << "path: " << pathFile << " page_number:" << inStr << " issue_id:" << g_Issueid << " pages:" << pageCheckout << endl;
	// Fill in the file upload field. This makes libcurl load data from the given file name when curl_easy_perform() is called.
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "preview_image",
				 CURLFORM_FILE, pathFile.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "page_number",
				 CURLFORM_COPYCONTENTS, inStr.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "issue_id",
				 CURLFORM_COPYCONTENTS, g_Issueid.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "pages",
				 CURLFORM_COPYCONTENTS, pageCheckout.c_str(),
				 CURLFORM_END);
	
	// Fill in the submit field too, even if this is rarely needed
	//curl_formadd(&formpost,
	//			 &lastptr,
	//			 CURLFORM_COPYNAME, "package_id",
	//			 CURLFORM_COPYCONTENTS, g_Package_id.c_str(),
	//			 CURLFORM_END);

	curl = curl_easy_init();
	// initalize custom header list (stating that Expect: 100-continue is not wanted
	headerlist = curl_slist_append(headerlist, buf);
	if(curl) {
		HTTPRequestHelper::setProxyServer(curl);
		// what URL that receives this POST
	//	curl_easy_setopt(curl, CURLOPT_URL, "http://debug.dev.test.audiencemedia.com/idtest/checkin.php");
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		// init post data to cms
		curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 300);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 300);
		res = curl_easy_perform(curl);
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			
			// then cleanup the formpost chain
			curl_formfree(formpost);
			// free slist
			curl_slist_free_all (headerlist);
			
			cout << "up image curl_easy_perform: " << res << endl;
			_error_info = "Checking in preview image error";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UPLOAD_FAILED);
			return FALSE;
		}
		// always cleanup 
		curl_easy_cleanup(curl);
		
		// then cleanup the formpost chain
		curl_formfree(formpost);
		// free slist
		curl_slist_free_all (headerlist);
		_error_info = "Checked in preview image successful";
		SaveLogCenterData(_error_info);
	}
	return TRUE;
}

/********************************************************************************************************************
 *****Function: progress
 *****Creator:  Toan Nguyen
 *****IN: void *p, double dltotal, double  dlnow, double ultotal, double  ulnow
 *****out: 
 *****Objective: calculate speed uploading/downloading
 ********************************************************************************************************************/
int HTTPRequestHelper::progress(void *p,
                    double dltotal, double  dlnow,
                    double ultotal, double  ulnow)
{
	struct myprogress *myp = (struct myprogress *)p;
	CURL *curl = myp->curl;
	double curtime = 0;
	double MinPos = myp->MinPos;
	double MaxPos = myp->MaxPos;
	bool EnableDownload = myp->DownUp;
	RangeProgressBar *progressBar = myp->Progress;
	double Pos = 0;
	curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime);
	
	if (EnableDownload == UPLOADCOMMAND)
	{
		if(ultotal > 0)
		{
			Pos = (ulnow / (double)ultotal) * 100 / (double) 100 * (MaxPos - MinPos);
		}else
		{
			myp->lastruntime += 8;
			Pos = myp->lastruntime;
		}
	}else if(EnableDownload == DOWNLOADCOMMAND)
	{
		if(dltotal > 0)
		{
			Pos = (dlnow / (double)dltotal) * 100 / (double) 100 * (MaxPos - MinPos);
		}else
		{
			myp->lastruntime += 2;
			Pos = myp->lastruntime;
		}
		//cout << "progress bar pos: " << Pos << endl;
	}
	
	progressBar->SetPosition(MinPos + (int32)Pos);
	//cout << "up: " << ulnow << " or: " << ultotal << " Down: " << dlnow << " or:" << dltotal << endl;
	return 0;
}

/********************************************************************************************************************
 *****Function: PostStoryContentToCMS
 *****Creator:  Toan Nguyen
 *****IN: const string issueID, const string storyID, const string &pathFile, const string storySessionID
 *****out: 
 *****Objective: check in story/content/icml to Audience Media CMS
 ********************************************************************************************************************/
int HTTPRequestHelper::PostStoryContentToCMS(const string issueID, const string storyID, const string &pathFile, const string storySessionID) {
	string _error_info;
	struct myprogress prog;
	//double curtime = 0;
	RangeProgressBar *progressBar;
	progressBar = new RangeProgressBar("Checking in...", 0, 200, kTrue, kFalse, nil, kFalse);
	//progressBar->SetPosition(1);
	CURL *curl;
	CURLcode res;
	string buffer;
	
	string Domain;
	//string fileZip;
	string apiPrefix = API_PREFIX;
	
	//PMString str("please wait");
	
	Domain = g_Domain + "/" + apiPrefix + "/story/checkin";
	
	//fileZip = AMPUtils::getNameFromURL(pathFile);
	//progressbar.SetPosition(15);
	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;
	struct curl_slist *headerlist=NULL;
	static const char buf[] = "Content-Type: multipart/form-data";
	//progressBar->SetPosition(5);
	//string postdata = readFileBytes(pathFile);
	//progressbar.SetPosition(25);
	// Fill in the file upload field. This makes libcurl load data from the given file name when curl_easy_perform() is called.
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "file",
				 CURLFORM_FILE, pathFile.c_str(),
				 CURLFORM_END);
	
	// Fill in the filename field
	//curl_formadd(&formpost,
	//			 &lastptr,
	//			 CURLFORM_COPYNAME, "data",
	//			 CURLFORM_COPYCONTENTS, postdata.c_str(),
	//			 CURLFORM_END);
	
	// Fill in the submit field too, even if this is rarely needed
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "story_id",
				 CURLFORM_COPYCONTENTS, storyID.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "session_id",
				 CURLFORM_COPYCONTENTS, storySessionID.c_str(),
				 CURLFORM_END);

	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "issue_id",
				 CURLFORM_COPYCONTENTS, issueID.c_str(),
				 CURLFORM_END);
	
	curl = curl_easy_init();
	// initalize custom header list (stating that Expect: 100-continue is not wanted
	headerlist = curl_slist_append(headerlist, buf);
	//sprogressBar->SetPosition(15);
	if(curl) {
		prog.lastruntime = 0;
		prog.curl = curl;
		prog.MinPos = 0;
		prog.MaxPos = 200;
		prog.DownUp = UPLOADCOMMAND;
		prog.Progress = progressBar;
		HTTPRequestHelper::setProxyServer(curl);
		// what URL that receives this POST 
		//curl_easy_setopt(curl, CURLOPT_URL, "http://debug.dev.test.audiencemedia.com/idtest/checkin.php");
		//curl_easy_setopt(curl, CURLOPT_URL, "http://story.api.test.audiencemedia.com/api/amp/v1/indesign/story");
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 300);
		//curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime);
		// progress function 
		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress);
		// pass the struct pointer into the progress function 
		curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog);
		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
		//<-- end of progress fuction
		//curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		// init post data to cms
		curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
		//-----Add to get key to upload cover image----
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);		
		//-------------------EOF-----------------------
		res = curl_easy_perform(curl);
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			
			// then cleanup the formpost chain
			curl_formfree(formpost);
			// free slist
			curl_slist_free_all (headerlist);
			
			cout << "post story curl_easy_perform: " << res << endl;
			_error_info = "Failed to checking in story";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UPLOAD_FAILED);
			progressBar->~RangeProgressBar();
			return FALSE;
		}
		cout << "check in story:" << buffer << endl;
		progressBar->SetPosition(200);
		curl_easy_cleanup(curl);
		
		// then cleanup the formpost chain
		curl_formfree(formpost);
		// free slist
		curl_slist_free_all (headerlist);
		//-----Add to get key to upload cover image----
		//Json::Value root;   // will contains the root value after parsing.
		//Json::Reader reader;
		progressBar->SetPosition(200);

		if (buffer.find("\"success\":true") == string::npos)
		{
			cout << "cannot parse JSON PostStoryContentToCMS" << endl;
			_error_info = "Failed to checking in story, cannot parsing json";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UPLOAD_FAILED);
			//progressBar->SetPosition(200);
			progressBar->~RangeProgressBar();
			return FALSE;
		}
		/*
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			cout << "cannot parse JSON PostStoryContentToCMS" << endl;
			//progressBar->SetPosition(200);
			progressBar->~RangeProgressBar();
			return FALSE;
		}
		const Json::Value success = root["success"];
		if (success.asBool() == false) {
			//Json::Value errorText = root["text"];
			cout << "FALSE PostStoryContentToCMS" << endl;
			progressBar->~RangeProgressBar();
			return FALSE;
		}
		 */
		//const Json::Value package_id = root["package_id"];
		//g_Package_id = package_id.asString();
#if _INDESIG_DEBUG
		//cout << "package_id: " << g_Package_id << endl;
		//cout << "buffer: " << buffer << endl;
#endif
		//-------------------EOF-----------------------
		// always cleanup 
		//curl_easy_cleanup(curl);
		
		// then cleanup the formpost chain
		//curl_formfree(formpost);
		// free slist
		//curl_slist_free_all (headerlist);
		_error_info = "Checked in story successful";
		SaveLogCenterData(_error_info);
		progressBar->~RangeProgressBar();
	}
	//cout << "check in story success" << endl;
	return TRUE;
}

/********************************************************************************************************************
 *****Function: GetStoryContentFromCMS
 *****Creator:  Toan Nguyen
 *****IN: const string issueID, const string storyID, string &errorStr, string &sessionIDStr
 *****out: 
 *****Objective: check out content/story/icml from Audience Media cms
 ********************************************************************************************************************/
int HTTPRequestHelper::GetStoryContentFromCMS(const string issueID, const string storyID, string &errorStr, string &sessionIDStr) {

	string headerLine;
	string _error_info;
	/////////////////////////////////////////////////////////////////////////////////
	// Get icml url 
	/////////////////////////////////////////////////////////////////////////////////
	struct myprogress prog;
	//double curtime = 0;
	RangeProgressBar *progressBar;
	progressBar = new RangeProgressBar("Checking out story...", 0, 200, kTrue, kFalse, nil, kFalse);
	CURL *curl;
	CURLcode result;
	string buffer;
	string Domain;
	string icmlURL;
	string timeup;
	//string fileZip;
	string apiPrefix = API_PREFIX;
	AMPUtils::CalculateTimer(TRUE);
	//Domain = g_Domain + "/" + apiPrefix + "/story/checkout/" + storyID.c_str();/story/checkoutpartial/
	Domain = g_Domain + "/" + apiPrefix + "/story/checkout/" + issueID + "/" + storyID;
	//Domain = g_Domain + "/" + apiPrefix + "/story/checkoutpartial/" + issueID + "/" + storyID;	//<--20121210
	cout << "Domain: " << Domain << endl;
	curl = curl_easy_init();
	
	if (curl)
	{
		HTTPRequestHelper::setProxyServer(curl);
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
		//////--------xxxxxxx---------------------------
		curl_easy_setopt(curl, CURLOPT_WRITEHEADER, &headerLine);
		///////-------uuuuuuuuuuuuuuu-------------------
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 600);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 600);
		result = curl_easy_perform(curl);//http get performed
		
		curl_easy_cleanup(curl);//must cleanup
		//cout << "++Response header:" << headerLine << endl;
		//error codes: http://curl.haxx.se/libcurl/c/libcurl-errors.html
		if (result != CURLE_OK) {
			//cout << "False to check out story" << endl;
			timeup = AMPUtils::CalculateTimer(FALSE);
			errorStr = "\n\nCheck-out Failed. Please try again.";
			_error_info = "Check-out story Failed. Total time check out: " + timeup + "s";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_DOWNLOADING_FAILED);
			progressBar->~RangeProgressBar();
			return FALSE;
		}

		//curl_easy_strerror was added in libcurl 7.12.0
		//cerr << "error: " << result << " " << curl_easy_strerror(result) <<endl;
		//cout << "buffer: " << buffer << endl;
		Json::Value root;   // will contains the root value after parsing.
		Json::Reader reader;
		//progressBar->SetPosition(200);
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			//cout << "cannot parse JSON from GetStoryContentFromCMS:" << buffer << endl;
			//progressBar->SetPosition(200);
			errorStr = "\n\nCheck-out Failed. Please try again.";
			timeup = AMPUtils::CalculateTimer(FALSE);
			_error_info = "Check-out Failed. Total time generating url: " + timeup;
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_DOWNLOADING_FAILED);
			progressBar->~RangeProgressBar();
			return FALSE;
		}
		
		// check locked key
		const Json::Value success = root["success"];
		if (success.asBool() == FALSE) {
			//cout << "get success: " << endl;
			Json::Value errorText = root["text"];
			errorStr = "\n\n" + errorText.asString();
			_error_info = "Failed to checking out story from server, status text:" + errorText.asString();
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_DOWNLOADING_FAILED);
			//errorStr = errorText.asString();
			progressBar->~RangeProgressBar();
			return FALSE;
		}
		
		timeup = AMPUtils::CalculateTimer(FALSE);
		_error_info = "time wait for request checkout: " + timeup + "s";
		SaveLogCenterData(_error_info);
		const Json::Value icml_url = root["icml_url"];
		icmlURL = icml_url.asString();
		cout << "icmlURL:" << icmlURL << endl;
		const Json::Value icml_sessionID = root["session"]["session_id"];
		sessionIDStr = icml_sessionID.asString();
	}
	
	progressBar->SetPosition(50);
	
	/////////////////////////////////////////////////////////////////////////////////
	// Get icml file 
	/////////////////////////////////////////////////////////////////////////////////
	CURL *icml_curl;
	CURLcode icml_result;
	FILE *ftpfile;
	FILE *respfile;
	
	// generate filename from url
	//string filename = url.substr(url.find_last_of("/")+1);
	//string ftpFilePath = g_System_WorkspaceDir + "/" + storyID.c_str() + ".icml"; 
	string ftpFilePath = g_System_WorkspaceDir + "/" + storyID.c_str() + ".zip"; 
	//string sdkfilename = g_SDK_WorkspaceDir + ":" + filename;
	string respfilePath = g_System_WorkspaceDir + "/resp" + storyID.c_str() + ".txt";
	const char *filePath = ftpFilePath.c_str();
	const char *respFilePath = respfilePath.c_str();
	

	//cout << "ftpFilepath: " << ftpFilePath << endl;
	
	/* local file name to store the file as */ 
	ftpfile = fopen(filePath, "wb"); /* b is binary, needed on win32 */ 
	
	/* local file name to store the FTP server's response lines in */ 
	respfile = fopen(respFilePath, "wb"); /* b is binary, needed on win32 */ 
	AMPUtils::CalculateTimer(TRUE);
	icml_curl = curl_easy_init();
	if(icml_curl) {
		
		prog.lastruntime = 0;
		prog.curl = icml_curl;
		prog.MinPos = 50;
		prog.MaxPos = 200;
		prog.DownUp = DOWNLOADCOMMAND;
		prog.Progress = progressBar;
		HTTPRequestHelper::setProxyServer(icml_curl);
		/* Get a file listing from sunet */ 
		curl_easy_setopt(icml_curl, CURLOPT_URL, icmlURL.c_str());
		// progress function 
		curl_easy_setopt(icml_curl, CURLOPT_PROGRESSFUNCTION, progress);
		// pass the struct pointer into the progress function 
		curl_easy_setopt(icml_curl, CURLOPT_PROGRESSDATA, &prog);
		curl_easy_setopt(icml_curl, CURLOPT_NOPROGRESS, 0L);
		//<-- end of progress fuction
		curl_easy_setopt(icml_curl, CURLOPT_WRITEDATA, ftpfile);
		/* If you intend to use this on windows with a libcurl DLL, you must use
		 CURLOPT_WRITEFUNCTION as well */ 
		//curl_easy_setopt(icml_curl, CURLOPT_HEADERFUNCTION, HTTPRequestHelper::file_write_response);
		curl_easy_setopt(icml_curl, CURLOPT_HEADERFUNCTION, HTTPRequestHelper::header_response);
		curl_easy_setopt(icml_curl, CURLOPT_WRITEHEADER, respfile);
	
		curl_easy_setopt(icml_curl, CURLOPT_CONNECTTIMEOUT, 400);
		curl_easy_setopt(icml_curl, CURLOPT_TIMEOUT, 400);
		icml_result = curl_easy_perform(icml_curl);
		//cout << "--Response header:" << headerLine << endl;
		/* always cleanup */ 
		curl_easy_cleanup(icml_curl);
		
		if (icml_result != CURLE_OK) {
			//cout << "false to download icml" << endl;
			errorStr = "\n\nCheck-out Failed. Please try again.";
			timeup = AMPUtils::CalculateTimer(FALSE);
			_error_info = "Check-out Failed. Total time download: " + timeup + "s";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_DOWNLOADING_FAILED);
			progressBar->~RangeProgressBar();
			fclose(ftpfile); /* close the local file */ 
			fclose(respfile); /* close the response file */ 
			return FALSE;
		}

	}
	timeup = AMPUtils::CalculateTimer(FALSE);
	_error_info = "time wait for requesting download icml: " + timeup + "s";
	SaveLogCenterData(_error_info);
	progressBar->SetPosition(200);
	fclose(ftpfile); /* close the local file */ 
	fclose(respfile); /* close the response file */ 
	//cout << "downloaded icml" << endl;

	/* 
		unzip story
	*/
	string excutePath = "cd " + g_System_WorkspaceDir + " && tar -xvf ";
	excutePath += filePath;
	//cout << "System command: " << excutePath << "\nPath download " << filePath << endl;
	system(excutePath.c_str());
	////////////////////////////
	_error_info = "Checked out story from CMS successful";
	SaveLogCenterData(_error_info);
	progressBar->~RangeProgressBar();
	return TRUE;
}

/********************************************************************************************************************
 *****Function: UnlockStory
 *****Creator:  Toan Nguyen
 *****IN: const string issueID, const string storyID
 *****out: 
 *****Objective: unlock story
 ********************************************************************************************************************/
int HTTPRequestHelper::UnlockStory(const string issueID, const string storyID) {

	string _error_info;
	struct myprogress prog;
	RangeProgressBar *progressBar;
	progressBar = new RangeProgressBar("Unlocking Stories...", 0, 200, kTrue, kFalse, nil, kFalse);
	
	string buffer;
	
	CURL *curl;
	CURLcode result;
	string Domain;
	string apiPrefix = API_PREFIX;
	Domain = g_Domain + "/" + apiPrefix + "/story/unlockStory";
	//string postPara = "package_id=" + g_Package_id + "&story=" + storyID.c_str();
	string postPara = "issue_id=" + issueID + "&story=" + storyID;
	cout<< "postPara" << postPara << endl;
	curl = curl_easy_init();
	
	if (curl)
	{
		prog.lastruntime = 0;
		prog.curl = curl;
		prog.MinPos = 0;
		prog.MaxPos = 200;
		prog.DownUp = DOWNLOADCOMMAND;
		prog.Progress = progressBar;
		HTTPRequestHelper::setProxyServer(curl);
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postPara.c_str());
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 50);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 50);
		
		result = curl_easy_perform(curl);//http get performed
		
		curl_easy_cleanup(curl);//must cleanup
		
		//error codes: http://curl.haxx.se/libcurl/c/libcurl-errors.html
		if (result == CURLE_OK)
		{
			//errorStr = "Audience Media InDesign Plug-in\n\nCannot check out story content from CMS\n\nPlease try again";
			_error_info = "Cannot unlock story content from plugin";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UNLOCK_STORY_FAILED);
			
			progressBar->SetPosition(200);
			progressBar->~RangeProgressBar();
			cout << "unlock result: " << buffer << endl;
 			return TRUE;
		}
		
		//curl_easy_strerror was added in libcurl 7.12.0
		cerr << "error: " << result << " " << curl_easy_strerror(result) <<endl;
	}
	_error_info = "unlock story content from plugin successful";
	SaveLogCenterData(_error_info);

	progressBar->SetPosition(200);
	progressBar->~RangeProgressBar();
	
	return FALSE;
	
}

/********************************************************************************************************************
 *****Function: UnlockPackage
 *****Creator:  Toan Nguyen
 *****IN: const string issueID, const string pages
 *****out: 
 *****Objective: unlock package
 ********************************************************************************************************************/
int HTTPRequestHelper::UnlockPackage(const string issueID, const string pages) {
	string _error_info;
	struct myprogress prog;
	RangeProgressBar *progressBar;
	progressBar = new RangeProgressBar("Unlocking Package...", 0, 200, kTrue, kFalse, nil, kFalse);
	
	string buffer;
	
	CURL *curl;
	CURLcode result;
	string Domain;
	string apiPrefix = API_PREFIX;
	Domain = g_Domain + "/" + apiPrefix + "/story/unlockPackage";
	//string postPara = "package_id=" + g_Package_id;
	string unlockPages = pages.c_str();
	while (unlockPages.find(" ") != string::npos) {
		unlockPages.replace(unlockPages.find(" "), 1, "");
	}
	unlockPages.erase(unlockPages.length()-1, unlockPages.length()); // remove the last ","
	string postPara = "issue_id=" + issueID + "&pages=" + unlockPages.c_str();
	
	curl = curl_easy_init();
	
	if (curl)
	{
		prog.lastruntime = 0;
		prog.curl = curl;
		prog.MinPos = 0;
		prog.MaxPos = 200;
		prog.DownUp = DOWNLOADCOMMAND;
		prog.Progress = progressBar;
		HTTPRequestHelper::setProxyServer(curl);
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postPara.c_str());
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 50);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 50);
		
		result = curl_easy_perform(curl);//http get performed
		
		curl_easy_cleanup(curl);//must cleanup
		
		//error codes: http://curl.haxx.se/libcurl/c/libcurl-errors.html
		if (result == CURLE_OK)
		{
			_error_info = "Cannot unlock pages from plugin";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UNLOCK_PAGES_FAILED);
			
			progressBar->SetPosition(200);
			progressBar->~RangeProgressBar();
			cout << "unlock result: " << buffer << endl;
 			return TRUE;
		}
		
		//curl_easy_strerror was added in libcurl 7.12.0
		cerr << "error: " << result << " " << curl_easy_strerror(result) <<endl;
	}
	_error_info = "unlock pages from plugin successfully";
	SaveLogCenterData(_error_info);
	progressBar->SetPosition(200);
	progressBar->~RangeProgressBar();
	
	return FALSE;
	
}

/********************************************************************************************************************
 *****Function: RequestSession
 *****Creator:  Toan Nguyen
 *****IN: 
 *****out: 
 *****Objective: update new session
 ********************************************************************************************************************/
int HTTPRequestHelper::RequestSession()
{
	string _error_info;
	CURL *curl;
	CURLcode res;
	string Domain;
	string apiPrefix = API_PREFIX;
	string buffer;
	Domain = g_Domain + "/" + apiPrefix + "/session/update/";
	Domain += n_mSessionID;
	//cout << "Domain update session: " << Domain << " *Session_id " << n_mSessionID << endl;
	curl = curl_easy_init();
	
	if(curl) {
		HTTPRequestHelper::setProxyServer(curl);
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 50);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 50);
		res = curl_easy_perform(curl);
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			//cout << "update sesssion curl_easy_perform: " << res << endl;
			_error_info = "Cannot update session from plugin";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UPDATE_SESSION_FAILED);
			
			return -2;
		}
		// always cleanup 
		curl_easy_cleanup(curl);
		
		cout << buffer << endl;
		// Analysic json link
		Json::Value root;   // will contains the root value after parsing.
		Json::Reader reader;
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			//cout << "cannot parse JSON HTTPRequestHelper::RequestSession" << endl;
			_error_info = "Cannot update session from plugin, cannot parsing json";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UPDATE_SESSION_FAILED);
			return FALSE;
		}
		const Json::Value success = root["success"];
		if (success.asBool() == FALSE) {
			const Json::Value errorText = root["text"];
			string err = errorText.asString();
			//cout << "errorText: " << err << endl;
			
			_error_info = "Cannot update session from plugin, status text:" + errorText.asString();
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UPDATE_SESSION_FAILED);
			return -1;
		}
	}
	//_error_info = "Update session from plugin successfully";
	//SaveLogCenterData(_error_info);
	AMPUtils::SaveDocument();	//Toan added here
	return TRUE;
}

/********************************************************************************************************************
 *****Function: RenewSession
 *****Creator:  Toan Nguyen
 *****IN: string Session_id
 *****out: 
 *****Objective: renew session
 ********************************************************************************************************************/
string HTTPRequestHelper::RenewSession(string Session_id) {
	string _error_info;
	CURL *curl;
	CURLcode res;
	string Domain;
	string apiPrefix = API_PREFIX;
	string buffer;

	Domain = g_Domain + "/" + apiPrefix + "/session/renew/" + Session_id;
	cout << "renewsession url: " << Domain << endl;
	//string authentication = g_Username + ":" + g_Password;
	
	/*
	{
		"success": true,
		"text": "Renew session successfully",
		"session": {
			"session_id": "d250415f1aeb7f0a2dec93f2bf9290b8",
			"session_timeout": 3600,
			"user_id": "2172"
		}
	}
	 */
	
	curl = curl_easy_init();
	// initalize custom header list (stating that Expect: 100-continue is not wanted
	if(curl) {
		HTTPRequestHelper::setProxyServer(curl);
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		//curl_easy_setopt(curl, CURLOPT_USERPWD, authentication.c_str());
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 50);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 50);
		res = curl_easy_perform(curl);
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			//cout << "renew session curl_easy_perform: " << res << endl;
			_error_info = "Cannot renew session from plugin";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_RENEW_SESSION_FAILED);
			return "";
		}
		// always cleanup 
		curl_easy_cleanup(curl);
		
		cout << buffer << endl;
		
		// Analysic json link
		Json::Value root;   // will contains the root value after parsing.
		Json::Reader reader;
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			//cout << "cannot parse JSON HTTPRequestHelper::RenewSession" << endl;
			_error_info = "Cannot renew session from plugin, cannot parsing json";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_RENEW_SESSION_FAILED);
			return "";
		}
		
		const Json::Value success = root["success"];
		if (success.asBool() == FALSE) {
			const Json::Value errorText = root["text"];
			_error_info = "Cannot renew session from plugin, status text:" + errorText.asString();
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_RENEW_SESSION_FAILED);
			return "";
		}
		
		const Json::Value newSessionuserID = root["session"]["user_id"];
		const Json::Value newSessiontimeout = root["session"]["session_expire_timeout"];
		const Json::Value newSessionID = root["session"]["session_id"];
		
		n_mSessionUserID = newSessionuserID.asString();
		n_mSessionTimeOut = newSessiontimeout.asInt();
		
		//_error_info = "renew session from plugin successfully";
		//SaveLogCenterData(_error_info);
		AMPUtils::SaveDocument();	//Toan added here
		return newSessionID.asString();
	}
	return "";
}

/********************************************************************************************************************
 *****Function: RequestStorySession
 *****Creator:  Toan Nguyen
 *****IN: const string &storySessionID
 *****out: 
 *****Objective: update new story session 
 ********************************************************************************************************************/
int HTTPRequestHelper::RequestStorySession(const string &storySessionID)
{
	CURL *curl;
	CURLcode res;
	string Domain;
	string apiPrefix = API_PREFIX;
	string buffer;
	
	Domain = g_Domain + "/" + apiPrefix + "/session/update/";
	Domain += storySessionID.c_str();
	//cout << "Domain update session: " << Domain << endl;
	curl = curl_easy_init();
	
	if(curl) {
		HTTPRequestHelper::setProxyServer(curl);
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 50);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 50);
		res = curl_easy_perform(curl);
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			cout << "request story curl_easy_perform: " << res << endl;
			
			return FALSE;
		}
		// always cleanup 
		curl_easy_cleanup(curl);
		
		cout << buffer << endl;
		// Analysic json link
		Json::Value root;   // will contains the root value after parsing.
		Json::Reader reader;
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			cout << "cannot parse JSON HTTPRequestHelper::RequestStorySession" << endl;
			return FALSE;
		}
		
		const Json::Value success = root["success"];
		if (success.asBool() == FALSE) {
			const Json::Value errorText = root["text"];
			string err = errorText.asString();
			cout << "errorText: " << err << endl;
			return -1;
		}
		AMPUtils::SaveDocument();	//Toan added here
	}
	return TRUE;
}

/********************************************************************************************************************
 *****Function: getPackageURL
 *****Creator:  Toan Nguyen
 *****IN: 
 *****out: 
 *****Objective: get package from url
 ********************************************************************************************************************/
string HTTPRequestHelper::getPackageURL(const string &url, string &error) {
	RangeProgressBar *_progress;
	_progress = new RangeProgressBar("Loading...", 0, 500, kTrue, kFalse, nil, kFalse);
	string _error_info;
	CURL *curl;
	CURLcode res;
	string buffer;
	string Domain;
	string urlRequest;
	string pageCheckout;
	string apiPrefix = API_PREFIX;
	long   respcode;
	string timeup;
	Domain = g_Domain + "/" + apiPrefix + "/pages";
	//Domain = g_Domain + "/" + apiPrefix + "/fillpages";	//<--20121210
	//Domain = "http://story.api.test.audiencemedia.com/api/amp/v2/indesign/pages";
	//cout << "getPackageURL: " << Domain << endl;
	pageCheckout = g_pageNumberCheckOut;
	while (pageCheckout.find(" ") != string::npos)
	{
		pageCheckout.replace(pageCheckout.find(" "), 1, "");
	}
	pageCheckout.erase(pageCheckout.length()-1, pageCheckout.length());
	g_pageCheckIn = pageCheckout;
	cout << "g_Issueid - page: " << g_Issueid << " - " << pageCheckout << " - " << g_Resolution << endl;
	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;
	struct curl_slist *headerlist=NULL;
	static const char buf[] = "Content-Type: multipart/form-data";
	// Fill in the file upload field. This makes libcurl load data from the given file name when curl_easy_perform() is called.
	// Fill in the submit field too, even if this is rarely needed
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "issue_id",
				 CURLFORM_COPYCONTENTS, g_Issueid.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "pages",
				 CURLFORM_COPYCONTENTS,  pageCheckout.c_str(),
				 CURLFORM_END);
	
	//curl_formadd(&formpost,
	//			 &lastptr,
	//			 CURLFORM_COPYNAME, "page_id",
	//			 CURLFORM_COPYCONTENTS,  g_Pageid.c_str(),
	//			 CURLFORM_END);
	
	//curl_formadd(&formpost,
	//			 &lastptr,
	//			 CURLFORM_COPYNAME, "story_id",
	//			 CURLFORM_COPYCONTENTS, g_Storyid.c_str(),
	//			 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "resolution",
				 CURLFORM_COPYCONTENTS, g_Resolution.c_str(),
				 CURLFORM_END);
	AMPUtils::CalculateTimer(TRUE);
	curl = curl_easy_init();
	// initalize custom header list (stating that Expect: 100-continue is not wanted
	headerlist = curl_slist_append(headerlist, buf);
	//sprogressBar->SetPosition(15);
	if(curl) {
		HTTPRequestHelper::setProxyServer(curl);
		_progress->SetPosition(8);
		// progress function 
		struct myprogress AMPDlgProg;
		AMPDlgProg.lastruntime = 0;
		AMPDlgProg.curl = curl;
		AMPDlgProg.MinPos = 10;
		AMPDlgProg.MaxPos = 470;
		AMPDlgProg.DownUp = DOWNLOADCOMMAND;
		AMPDlgProg.Progress = _progress;
		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress);
		curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &AMPDlgProg);
		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
		
		//curl_easy_setopt(curl, CURLOPT_URL, "http://debug.dev.test.audiencemedia.com/idtest/checkin.php");
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		//curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime);
		// init post data to cms
		curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
		//-----Add to get key to upload cover image----
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);	
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 9000);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 9000);
		//-------------------EOF-----------------------
		curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &respcode);
		res = curl_easy_perform(curl);
		
		
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			
			// then cleanup the formpost chain
			curl_formfree(formpost);
			// free slist
			curl_slist_free_all (headerlist);
			//cout << "Post error curl_easy_perform: " << res << endl;
			timeup = AMPUtils::CalculateTimer(FALSE);
			_error_info = "Cannot get package from url : " + g_Issueid + " - " +  pageCheckout + " - " + g_Resolution;
			_error_info = _error_info + " - Total time generating: " + timeup + "s";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_GET_PACKAGE_URL_FAILED);
			_progress->~RangeProgressBar();
			return "";
		}
		// always cleanup 
		curl_easy_cleanup(curl);
		
		// then cleanup the formpost chain
		curl_formfree(formpost);
		// free slist
		curl_slist_free_all (headerlist);
		//cout << "buffer:" << buffer << endl;
		// Analysic json link
		Json::Value root;   // will contains the root value after parsing.
		Json::Reader reader;
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			//cout << "FALSE cannot parse buffer to get package " << buffer << endl;
			error = "Failed to get page from server\n\nPlease try again";
			_error_info = "Cannot parsing json package : " + g_Issueid + " - " +  pageCheckout + " - " + g_Resolution;
			_error_info = _error_info + "Total time generating: " + timeup + "s";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_GET_PACKAGE_URL_FAILED);
			_progress->~RangeProgressBar();
			return "";
		}
		
		const Json::Value success = root["success"];
		if (success.asBool() == FALSE) {
			int getStatus = 0;
			Json::Value errorText = root["text"];
			error =  /*"Audience Media InDesign Plug-in\n\n" + */"\n\n" + errorText.asString();
			Json::Value _status = root["status"];
			getStatus = _status.asInt();
			cout << "FALSE to get url " << buffer << endl;
			_error_info = "Failed to get package : " + g_Issueid + " - " +  pageCheckout + " - " + g_Resolution + "\nStatus text:" + errorText.asString();
			_error_info = _error_info + "Total time generating: " + timeup + "s";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_GET_PACKAGE_URL_FAILED);
			_progress->~RangeProgressBar();
			if(getStatus == LOCKED_DATA_PLUGIN_CMS) {
				return "LOCKED";
			}else {
				return "";
			}
		}
		//SaveLogCenterData(buffer);
		const Json::Value available_story = root["checkStoryContain"];	// detect pages without story
		g_AvailableStory = available_story.asString();
		const Json::Value page_name = root["idml_file"];//package_id
		cout << "generate file: " << buffer << endl;
		//g_IDMLOpen = page_name.asString();
		g_Package_id = page_name.asString();
		g_Package_id = g_Package_id.erase(g_Package_id.find(".idml"), g_Package_id.length());
		const Json::Value pages_package = root["pages_package"];
		urlRequest = pages_package.asString();
		const Json::Value session_id = root["session"]["session_id"];
		n_mSessionID = session_id.asString();
		const Json::Value user_id = root["session"]["user_id"];
		n_mSessionUserID = user_id.asString();
		const Json::Value session_timeout = root["session"]["session_expire_timeout"];
		n_mSessionTimeOut = session_timeout.asInt();
		n_mSessionCounterReset = 0;
		n_mSessionTotalCounterReset = (n_mSessionTimeOut - 300)/180;
		
		if(g_captionImg.size() > 0) {
			g_captionImg.clear();
		}
		int32 CaptionSize = 0;
		caption_t addedCaptionImg;
		cout << "parse caption" << endl;
		const Json::Value captionNum = root["captionMap"]["caption_num"];
		if(captionNum == NULL)
		{
			cout << "caption null" << endl;
		}else {
			CaptionSize = captionNum.asInt();
		}

		stringstream numInstr;
		for(int xx = 0; xx < CaptionSize; xx++) {
			numInstr.str("");
			numInstr << xx;
			string numOutStr = numInstr.str();
			Json::Value nameSTR = root["captionMap"][numOutStr.c_str()];
			string caption_self = nameSTR.asString();
			addedCaptionImg.caption_self = caption_self;
			g_captionImg.push_back(addedCaptionImg);	
		}
		
		_error_info = "Get package url successful.";
		_error_info = _error_info + "Total time generating: " + timeup + "s";
		SaveLogCenterData(_error_info);
		_progress->~RangeProgressBar();
		return urlRequest;
	}
	_progress->~RangeProgressBar();
	return "";
}

/********************************************************************************************************************
 *****Function: UnlockPackagetoCheckOut
 *****Creator:  Toan Nguyen
 *****IN: 
 *****out: 
 *****Objective: unlock package for checkout
 ********************************************************************************************************************/
bool HTTPRequestHelper::UnlockPackagetoCheckOut(string &error) {
	string _error_info;
	CURL *curl;
	CURLcode res;
	string buffer;
	string Domain;
	string urlRequest;
	string apiPrefix = API_PREFIX;
	Domain = g_Domain + "/" + apiPrefix + "/story/unlockPage";
	
	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;
	struct curl_slist *headerlist=NULL;
	static const char buf[] = "Content-Type: multipart/form-data";
	
	string pageCheckout = g_pageNumberCheckOut;
	while (pageCheckout.find(" ") != string::npos) {
		pageCheckout.replace(pageCheckout.find(" "), 1, "");
	}
	pageCheckout.erase(pageCheckout.length()-1, pageCheckout.length()); // remove the last ","
	// Fill in the file upload field. This makes libcurl load data from the given file name when curl_easy_perform() is called.
	//curl_formadd(&formpost,
	//			 &lastptr,
	//			 CURLFORM_COPYNAME, "user_id",
	//			 CURLFORM_COPYCONTENTS, n_mSessionUserID.c_str(),
	//			 CURLFORM_END);
	
	//curl_formadd(&formpost,
	//			 &lastptr,
	//			 CURLFORM_COPYNAME, "package_id",
	//			 CURLFORM_COPYCONTENTS, g_Package_id.c_str(),
	//			 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "issue_id",
				 CURLFORM_COPYCONTENTS, g_Issueid.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "pages",
				 CURLFORM_COPYCONTENTS, pageCheckout.c_str(),
				 CURLFORM_END);
	
	cout << "unlock: " << Domain << endl;
	curl = curl_easy_init();
	// initalize custom header list (stating that Expect: 100-continue is not wanted
	headerlist = curl_slist_append(headerlist, buf);
	//sprogressBar->SetPosition(15);
	if(curl) {
		HTTPRequestHelper::setProxyServer(curl);
		//curl_easy_setopt(curl, CURLOPT_URL, "http://debug.dev.test.audiencemedia.com/idtest/checkin.php");
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		//curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime);
		// init post data to cms
		curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
		//-----Add to get key to upload cover image----
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);	
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 50);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 50);

		res = curl_easy_perform(curl);
		cout << "json: " << buffer << endl;
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			
			// then cleanup the formpost chain
			curl_formfree(formpost);
			// free slist
			curl_slist_free_all (headerlist);
			//cout << "unlock package curl_easy_perform: " << res << endl;
			_error_info = "Cannot unlock pages from plugin";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UNLOCK_PAGES_FAILED);
			
			return FALSE;
		}
		// always cleanup 
		curl_easy_cleanup(curl);
		
		// then cleanup the formpost chain
		curl_formfree(formpost);
		// free slist
		curl_slist_free_all (headerlist);
		
		// Analysic json link
		Json::Value root;   // will contains the root value after parsing.
		Json::Reader reader;
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			//cout << "cannot parse JSON HTTPRequestHelper::UnlockPackagetoCheckOut" << endl;
			error = "Failed to get page from server\n\nPlease try again";
			_error_info = "Cannot unlock pages from plugin, cannot parsing json";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UNLOCK_PAGES_FAILED);
			return FALSE;
		}
		
		const Json::Value success = root["success"];
		if (success.asBool() == FALSE) {
			Json::Value errorText = root["text"];
			error = errorText.asString();
			_error_info = "Cannot unlock pages from plugin, status text:" +  errorText.asString();
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UNLOCK_PAGES_FAILED);
			return FALSE;
		}
	
		if (res == CURLE_OK) {
			_error_info = "unlock pages from plugin successful";
			SaveLogCenterData(_error_info);
			return TRUE;
		}
		//curl_easy_strerror was added in libcurl 7.12.0
		
		cerr << "error: " << res << " " << curl_easy_strerror(res) <<endl;
		error = "Failed to connect to server\n\nPlease try again";
		
		return FALSE;
	}
	return FALSE;
}


string HTTPRequestHelper::getImagePreview(string urlImg, struct myprogress AMPDlgProg)
{
	string _error_info;
	CURL *curl;
	CURLcode res;
	FILE *ftpfile;
	FILE *respfile;
	string head_;
	// generate filename from url
	string filename = urlImg.substr(urlImg.find_last_of("/")+1);
	string ftpFilePath = g_System_logDirectory + "/" + filename; 
	string sdkfilename = g_SDK_logDirectory + ":" + filename;//audiencemedia_preview
	string respfilePath = g_System_logDirectory + "/resp" + filename;
	const char *filePath = ftpFilePath.c_str();
	const char *respFilePath = respfilePath.c_str();
	
	if(urlImg == "")
	{
		return g_SDK_logDirectory;
	}

	/* local file name to store the file as */ 
	//ftpfile = fopen("Macintosh HD:Projects:InDesign-Plugin:bbcgoodefood:1:11:aaa.jpg", "wb"); /* b is binary, needed on win32 */ 
	ftpfile = fopen(filePath, "wb"); /* b is binary, needed on win32 */ 
	
	/* local file name to store the FTP server's response lines in */ 
	respfile = fopen(respFilePath, "wb"); /* b is binary, needed on win32 */ 
	//respfile = fopen("Macintosh HD:Projects:InDesign-Plugin:bbcgoodefood:1:11:bbb.jpg", "wb"); /* b is binary, needed on win32 */ 
	
	curl = curl_easy_init();
	if(curl) {
		HTTPRequestHelper::setProxyServer(curl);
		/* Get a file listing from sunet */ 
		curl_easy_setopt(curl, CURLOPT_URL, urlImg.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, ftpfile);
		//_______________________________________________________
		// progress function 
		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress);
		curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &AMPDlgProg);
		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
		//_______________________________________________________
		curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HTTPRequestHelper::file_write_response);
		curl_easy_setopt(curl, CURLOPT_WRITEHEADER, respfile);
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 100);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 100);
		res = curl_easy_perform(curl);
		//cout << "head_" << head_ << endl;
		if(res != CURLE_OK)
		{
			fclose(ftpfile); /* close the local file */ 
			fclose(respfile); /* close the response file */
			_error_info = "Cannot get image default preview";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_GET_IMAGE_PREVIEW_DEFAULT_FAILED);
			
			AMPDlgProg.Progress->SetPosition(AMPDlgProg.MaxPos);
			return g_SDK_logDirectory;
			
		}
		/* always cleanup */ 
		curl_easy_cleanup(curl);
	}
	
	fclose(ftpfile); /* close the local file */ 
	fclose(respfile); /* close the response file */ 
	//string deleteLink = "rm -rf " + respfilePath;
	//system(deleteLink.c_str());
	AMPDlgProg.Progress->SetPosition(AMPDlgProg.MaxPos);
	cout << "sdkfilename:" << sdkfilename << endl;
	return sdkfilename;
}

/********************************************************************************************************************
 *****Function: CallLogCenter
 *****Creator:  Toan Nguyen
 *****IN: 
 *****out: 
 *****Objective: send message to log center
 ********************************************************************************************************************/
bool HTTPRequestHelper::CallLogCenter(string log_data, string log_code, string _log_type, string _log_id) {
	string _error_info;
	CURL *curl;
	CURLcode res;
	string buffer;
	string Domain, pathFile;
	string log_type = "1";
	string app_id = "1";
	string urlRequest;
	string pageCheckout;
	string apiPrefix = API_PREFIX;
	Domain = g_Domain + "/api/log/v1/create";
	pathFile = g_System_logDirectory + "/logcenter.txt";

	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;
	struct curl_slist *headerlist=NULL;
	static const char buf[] = "Content-Type: multipart/form-data";
	// Fill in the file upload field. This makes libcurl load data from the given file name when curl_easy_perform() is called.
	// Fill in the submit field too, even if this is rarely needed
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "log_file",
				 CURLFORM_FILE, pathFile.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "amlog_app_id",
				 CURLFORM_COPYCONTENTS, app_id.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "log_code",
				 CURLFORM_COPYCONTENTS,  log_code.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "log_type",
				 CURLFORM_COPYCONTENTS, log_type.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "log_data",
				 CURLFORM_COPYCONTENTS, log_data.c_str(),
				 CURLFORM_END);
	
	curl = curl_easy_init();
	// initalize custom header list (stating that Expect: 100-continue is not wanted
	headerlist = curl_slist_append(headerlist, buf);
	if(curl) {
		HTTPRequestHelper::setProxyServer(curl);
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		// init post data to cms
		curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
		//-----Add to get key to upload cover image----
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);	
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 300);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 300);
		//-------------------EOF-----------------------
		res = curl_easy_perform(curl);
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			
			// then cleanup the formpost chain
			curl_formfree(formpost);
			// free slist
			curl_slist_free_all (headerlist);
			cout << "logcenter error curl_easy_perform: " << res << endl;
			_error_info = "Failed to set logging info";
			SaveLogCenterData(_error_info);
			return FALSE;
		}
		// always cleanup 
		curl_easy_cleanup(curl);
		
		// then cleanup the formpost chain
		curl_formfree(formpost);
		// free slist
		curl_slist_free_all (headerlist);
		//cout << "logcenter:" << buffer << endl;
		// Analysic json link
		Json::Value root;   // will contains the root value after parsing.
		Json::Reader reader;
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			cout << "logcenter FALSE cannot parse buffer to get package " << buffer << endl;
			_error_info = "Failed to set logging info, cannot parsing JSON data " + buffer;
			SaveLogCenterData(_error_info);
			//error = "Audience Media InDesign Plug-in\n\nFailed to get page from server\n\nPlease try again";
			return FALSE;
		}
		
		const Json::Value success = root["success"];
		if (success.asBool() == FALSE) {
			Json::Value errorText = root["text"];
			//error =  /*"Audience Media InDesign Plug-in\n\n" + */errorText.asString();
			//cout << "logcenter FALSE to get url " << endl;
			_error_info = "Failed to set logging info, status text " + errorText.asString();
			SaveLogCenterData(_error_info);
			return FALSE;
		}
		
		if (res == CURLE_OK) {
			_error_info = "Setting logging info successful";
			SaveLogCenterData(_error_info);
			return TRUE;
		}
		//curl_easy_strerror was added in libcurl 7.12.0
		cerr << "error: " << res << " " << curl_easy_strerror(res) <<endl;
		return FALSE;
	}
	return FALSE;
}


void HTTPRequestHelper::UpdateStoryStatus() {
	if(g_assignmentPtr.size() <= 0)
		return;
	
	string _error_info;
	CURL *curl;
	CURLcode res;
	string buffer;
	string Domain;
	string urlRequest;
	string apiPrefix = API_PREFIX;
	Domain = g_Domain + "/" + apiPrefix + "/story/checkStatus";
	
	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;
	struct curl_slist *headerlist=NULL;
	static const char buf[] = "Content-Type: multipart/form-data";
	if(g_pageCheckIn == "" || g_issueEditing == "") {
		return;
	}
	//cout << "update status:" << g_pageCheckIn << " - issue:" << g_issueEditing << endl;
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "issue_id",
				 CURLFORM_COPYCONTENTS, g_issueEditing.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "pages",
				 CURLFORM_COPYCONTENTS, g_pageCheckIn.c_str(),
				 CURLFORM_END);
	
	//cout << "checkstatus: " << Domain << endl;
	curl = curl_easy_init();
	headerlist = curl_slist_append(headerlist, buf);
	if(curl) {
		HTTPRequestHelper::setProxyServer(curl);
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);	
		curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2);
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 2);
		
		res = curl_easy_perform(curl);
		cout << "stauts json: " << buffer << endl;
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			
			// then cleanup the formpost chain
			curl_formfree(formpost);
			// free slist
			curl_slist_free_all (headerlist);
			return;
		}
		// always cleanup 
		curl_easy_cleanup(curl);
		
		// then cleanup the formpost chain
		curl_formfree(formpost);
		// free slist
		curl_slist_free_all (headerlist);
		
		// Analysic json link
		Json::Value root;   // will contains the root value after parsing.
		Json::Reader reader;
		bool parsingSuccessful = reader.parse( buffer, root );
		if ( !parsingSuccessful )
		{
			return;
		}

		for (int i = 0; i < g_assignmentPtr.size(); i++) {
			pt_assignStr iStorylinkRef = g_assignmentPtr[i];
			string story_id = iStorylinkRef.story_id;
			const Json::Value status = root[story_id.c_str()];
			if(status == NULL) return;
			int storystatus = status.asInt();
			if(iStorylinkRef._status != storystatus) {
				g_assignmentPtr[i]._status = storystatus;
				AMPUtils::UpdateStatusProperties(iStorylinkRef.frameUIDRef, storystatus);
			}
		}
		//cout << "++update status endl" << endl;
	}
}

int HTTPRequestHelper::PostCaptionContentToCMS(const string captionID, const string &pathFile) {
	string _error_info;
	CURL *curl;
	CURLcode res;
	string buffer;
	string Domain;
	string apiPrefix = API_PREFIX;
	string storyID = captionID.substr(captionID.find("Caption_")+1);
	Domain = g_Domain + "/" + apiPrefix + "/story/checkin";
	cout << "path:" << pathFile << "\nupdate_caption:" << captionID << " - " << storyID << endl;
	struct curl_httppost *formpost=NULL;
	struct curl_httppost *lastptr=NULL;
	struct curl_slist *headerlist=NULL;
	static const char buf[] = "Content-Type: multipart/form-data";
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "file",
				 CURLFORM_FILE, pathFile.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "update_caption",
				 CURLFORM_COPYCONTENTS, captionID.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "story_id",
				 CURLFORM_COPYCONTENTS, storyID.c_str(),
				 CURLFORM_END);
	
	curl_formadd(&formpost,
				 &lastptr,
				 CURLFORM_COPYNAME, "issue_id",
				 CURLFORM_COPYCONTENTS, g_Issueid.c_str(),
				 CURLFORM_END);
	
	curl = curl_easy_init();
	// initalize custom header list (stating that Expect: 100-continue is not wanted
	headerlist = curl_slist_append(headerlist, buf);
	
	if(curl) {
		HTTPRequestHelper::setProxyServer(curl);
		// what URL that receives this POST 
		curl_easy_setopt(curl, CURLOPT_URL, Domain.c_str());
		curl_easy_setopt(curl, CURLOPT_USERPWD, g_Authentication.c_str());	//authentication login
		curl_easy_setopt(curl, CURLOPT_TIMEOUT, 300);
		// progress function 
		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress);
		// pass the struct pointer into the progress function 
		curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
		//-----Add to get key to upload cover image----
		curl_easy_setopt(curl, CURLOPT_HEADER, 0);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HTTPRequestHelper::writer);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);		
		//-------------------EOF-----------------------
		res = curl_easy_perform(curl);
		if(res != CURLE_OK)
		{
			// always cleanup 
			curl_easy_cleanup(curl);
			
			// then cleanup the formpost chain
			curl_formfree(formpost);
			// free slist
			curl_slist_free_all (headerlist);
			
			cout << "post caption curl_easy_perform: " << res << endl;
			_error_info = "Failed to checking in caption";
			SaveLogCenterData(_error_info);
			AMPLogCenter::DataLogCenter(AMPPLUGIN_UPLOAD_FAILED);
			return FALSE;
		}
		cout << "check in caption:" << buffer << endl;
		curl_easy_cleanup(curl);
		
		// then cleanup the formpost chain
		curl_formfree(formpost);
		// free slist
		curl_slist_free_all (headerlist);
		//-----Add to get key to upload cover image----

		_error_info = "Checked in caption successful";
		SaveLogCenterData(_error_info);
	}
	//cout << "check in story success" << endl;
	return TRUE;
}